/**
 * MindMap 思维导图组件
 * 
 * 功能描述：
 * 1. 基于 Markmap 库渲染 Markdown 格式的思维导图
 * 2. 支持历史数据展示和 SSE 流式实时渲染
 * 3. 支持节点点击交互，通过抽屉展示关联数据（表格/表单）
 * 4. 深度集成 Three.js 风格的 SVG 样式定制
 * 
 * 核心功能：
 * - 实时解析 Markdown
 * - 自定义 SVG 样式（节点背景、连接线、文字颜色）
 * - 交互控制（缩放、居中、展开/收缩）
 */
<template>
  <!-- 思维导图智能体显示内容 -->
  <div class="mindmap-wrapper">
    <!-- 加载中遮罩层（仅在历史数据模式下显示，SSE实时渲染不显示） -->
    <div v-if="isLoadingMindMap && isHistoryMode" class="loading-overlay">
      <img :src="loadingGif" alt="加载中" class="loading-gif" />
      <p class="loading-text">正在加载思维导图...</p>
    </div>

    <div id="mindMapContainer" class="mindmap-container">
      <!-- 思维导图控制按钮 -->
      <MindMapControls ref="controlsRef" :markmap-instance="markmapInstance" :raw-tree="rawTree"
        @update-zoom-level="handleZoomLevelUpdate" @update-collapsed="handleCollapsedUpdate"
        @reapply-styles="handleReapplyStyles" />
    </div>

    <!-- 抽屉组件 -->
    <transition name="drawer-slide">
      <div v-if="showDrawer" class="drawer-container">
        <div class="drawer-header">
          <span>{{ rootNodeName }}</span>
          <button @click="showDrawer = false" class="drawer-close-btn">✕</button>
        </div>
        <div class="drawer-content">
          <div class="drawer-actions">
            <button class="drawer-action-btn" @click="selectDrawerButton('A')">
              <img :src="selectedDrawerButton === 'A' ? sheetAS : sheetAX" alt="Pi次" class="drawer-btn-img" />
              <span class="drawer-btn-text">Pi次</span>
            </button>
            <button class="drawer-action-btn drawer-action-btn-2" @click="selectDrawerButton('B')">
              <img :src="selectedDrawerButton === 'B' ? sheetBS : sheetBX" alt="Hang线" class="drawer-btn-img" />
              <span class="drawer-btn-text">Hang线</span>
            </button>
          </div>
          <div class="drawer-text">
            <!-- 表格模式 -->
            <div v-if="drawerContentType === 'text'" class="table-container">
              <table class="data-table">
                <thead>
                  <tr>
                    <th>序号</th>
                    <th>名称</th>
                    <th>网格坐标</th>
                    <th>高度(百米)</th>
                    <th>速度(千米/时)</th>
                    <th>到达时刻</th>
                    <th>剩余油量(千克)</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="(item, index) in tableData" :key="item.id"
                    :class="{ 'odd-row': index % 2 === 0, 'even-row': index % 2 !== 0 }">
                    <td>{{ item.id }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.gridCoord }}</td>
                    <td>{{ item.altitude }}</td>
                    <td>{{ item.speed }}</td>
                    <td>{{ item.arrivalTime }}</td>
                    <td>{{ item.fuelRemaining }}</td>
                  </tr>
                </tbody>
              </table>
            </div>

            <!-- 表单模式 -->
            <div v-else-if="drawerContentType === 'form'" class="drawer-form">
              <!-- 第一列 -->
              <div class="form-column">
                <div class="form-field">
                  <label class="field-label">主renwu名称</label>
                  <select class="field-input" v-model="formData.mainTask">
                    <option :value="formData.mainTask">{{ formData.mainTask || '请选择' }}</option>
                  </select>
                </div>
                <div class="form-field">
                  <label class="field-label">wuqi挂载</label>
                  <select class="field-input" v-model="formData.weaponMount">
                    <option :value="formData.weaponMount">{{ formData.weaponMount || '请选择' }}</option>
                  </select>
                </div>
                <div class="form-field">
                  <label class="field-label">部bie</label>
                  <select class="field-input" v-model="formData.department">
                    <option :value="formData.department">{{ formData.department || '请选择' }}</option>
                  </select>
                </div>
                <div class="form-field">
                  <label class="field-label">准时到达-时刻</label>
                  <input type="text" class="field-input" v-model="formData.arrivalTime" />
                </div>
                <div class="form-field">
                  <label class="field-label">预计起飞时刻</label>
                  <input type="text" class="field-input" v-model="formData.takeoffTime" />
                </div>
                <div class="form-field">
                  <label class="field-label">通信规定-duanbe</label>
                  <input type="text" class="field-input" v-model="formData.commShortWave" />
                </div>
              </div>

              <!-- 第二列 -->
              <div class="form-column">
                <div class="form-field">
                  <label class="field-label">子renwu名称</label>
                  <select class="field-input" v-model="formData.subTask">
                    <option :value="formData.subTask">{{ formData.subTask || '请选择' }}</option>
                  </select>
                </div>
                <div class="form-field">
                  <label class="field-label">jixing</label>
                  <select class="field-input" v-model="formData.aircraftType">
                    <option :value="formData.aircraftType">{{ formData.aircraftType || '请选择' }}</option>
                  </select>
                </div>
                <div class="form-field">
                  <label class="field-label">youliang</label>
                  <input type="text" class="field-input" v-model="formData.fuelAmount" />
                </div>
                <div class="form-field">
                  <label class="field-label">fenxing段代号</label>
                  <input type="text" class="field-input" v-model="formData.flightSegment" />
                </div>
                <div class="form-field">
                  <label class="field-label">最低fanhang油量</label>
                  <input type="text" class="field-input" v-model="formData.minFuel" />
                </div>
                <div class="form-field">
                  <label class="field-label">遮盖规定-Jianyweteng</label>
                  <input type="text" class="field-input" v-model="formData.coverageRule" />
                </div>
              </div>

              <!-- 第三列 -->
              <div class="form-column">
                <div class="form-field">
                  <label class="field-label">目biao</label>
                  <input type="text" class="field-input" v-model="formData.target" />
                </div>
                <div class="form-field">
                  <label class="field-label">jia/zpi</label>
                  <input type="text" class="field-input" v-model="formData.callsign" />
                </div>
                <div class="form-field">
                  <label class="field-label">zhihu代码</label>
                  <input type="text" class="field-input" v-model="formData.commandCode" />
                </div>
                <div class="form-field">
                  <label class="field-label">fejnID号</label>
                  <input type="text" class="field-input" v-model="formData.tailNumber" />
                </div>
                <div class="form-field">
                  <label class="field-label">预计zhuobu时刻</label>
                  <input type="text" class="field-input" v-model="formData.landingTime" />
                </div>
                <div class="form-field">
                  <label class="field-label">zhihu单位</label>
                  <input type="text" class="field-input" v-model="formData.commandUnit" />
                </div>
              </div>

              <!-- 第四列 -->
              <div class="form-column">
                <div class="form-field">
                  <label class="field-label">renwu类型</label>
                  <select class="field-input" v-model="formData.taskType">
                    <option :value="formData.taskType">{{ formData.taskType || '请选择' }}</option>
                  </select>
                </div>
                <div class="form-field">
                  <label class="field-label">qijang机场</label>
                  <select class="field-input" v-model="formData.airfield">
                    <option :value="formData.airfield">{{ formData.airfield || '请选择' }}</option>
                  </select>
                </div>
                <div class="form-field">
                  <label class="field-label">准时到达-地点</label>
                  <input type="text" class="field-input" v-model="formData.arrivalLocation" />
                </div>
                <div class="form-field">
                  <label class="field-label">二次leida</label>
                  <input type="text" class="field-input" v-model="formData.secondaryRadar" />
                </div>
                <div class="form-field">
                  <label class="field-label">通信规定-chaoduanbo</label>
                  <input type="text" class="field-input" v-model="formData.commUltraShort" />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
/**
 * 思维导图组件
 * 
 * 核心功能：
 * 1. 解析并渲染 Markdown 格式的思维导图
 * 2. 点击叶子节点展示关联的 pici（表单）和 hangxian（表格）数据
 * 3. 提供缩放、重置、展开/收缩等交互控制
 */

// ==================== 依赖导入 ====================
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { Markmap } from 'markmap-view'
import MindMapControls from '../MindMap/MindMapControls.vue'

// 导入图片资源
import loadingGif from '../../assets/Common/loading-spinner.gif'
import sheetAS from '../../assets/MindMap/sheet-as.png'
import sheetAX from '../../assets/MindMap/sheet-ax.png'
import sheetBS from '../../assets/MindMap/sheet-bs.png'
import sheetBX from '../../assets/MindMap/sheet-bx.png'

// ==================== 组件接口 ====================
const props = defineProps<{
  receivedMessage: string
  showMindMap: boolean
  isHistoryMode: boolean  // 是否为历史数据模式
}>()

const emit = defineEmits<{
  mindmapLoadingCompleted: []
}>()

// ==================== 响应式状态 ====================
const markdownContent = ref<string>('')
const zoomLevel = ref<number>(50)
const isLoadingMindMap = ref<boolean>(false)
const isCollapsed = ref<boolean>(false)
const isInitialized = ref<boolean>(false)
const rootNodeName = ref<string>('')
const controlsRef = ref<InstanceType<typeof MindMapControls> | null>(null)
let markmapInstance: any = null
let rawTree: any = null

const showDrawer = ref<boolean>(false)
const selectedDrawerButton = ref<'A' | 'B'>('A')
const drawerContentType = ref<'text' | 'form'>('form')

// 表单数据
const formData = ref({
  mainTask: '',
  weaponMount: '',
  department: '',
  arrivalTime: '',
  takeoffTime: '',
  commShortWave: '',
  subTask: '',
  aircraftType: '',
  fuelAmount: '',
  flightSegment: '',
  minFuel: '',
  coverageRule: '',
  target: '',
  callsign: '',
  commandCode: '',
  tailNumber: '',
  landingTime: '',
  commandUnit: '',
  taskType: '',
  airfield: '',
  arrivalLocation: '',
  secondaryRadar: '',
  commUltraShort: ''
})

const tableData = ref<any[]>([])

// ==================== 事件处理 ====================

/**
 * 处理缩放级别更新
 */
const handleZoomLevelUpdate = (level: number) => {
  zoomLevel.value = level
}

/**
 * 处理收缩状态更新
 */
const handleCollapsedUpdate = (collapsed: boolean) => {
  isCollapsed.value = collapsed
}

/**
 * 重新应用样式
 */
const handleReapplyStyles = () => {
  const container = document.getElementById('mindMapContainer')
  const svg = container?.querySelector('svg')
  if (svg) {
    applyMarkmapStyles(svg as SVGElement)
  }
}

// ==================== 数据提取函数 ====================

/**
 * 从 Markdown 中提取节点关联的 pici 和 hangxian 数据
 * @param nodeText 节点文本内容
 * @returns 包含 piciData 和 hangxianData 的对象
 */
const extractDataFromMarkdown = (nodeText: string): { piciData: any | null, hangxianData: any[] | null } => {
  const lines = markdownContent.value.split('\n')
  let piciData: any = null
  let hangxianData: any[] | null = null

  const nodeLineIndex = lines.findIndex(line => {
    const cleanLine = line.replace(/^#+\s*/, '').trim()
    return cleanLine === nodeText.trim()
  })

  if (nodeLineIndex === -1) {
    console.warn('未找到节点文本对应的行:', nodeText)
    return { piciData, hangxianData }
  }

  for (let i = nodeLineIndex + 1; i < lines.length; i++) {
    const line = lines[i].trim()
    const hasPici = line.includes('{pici:')
    const hasHangxian = line.includes('{hangxian:')

    if (line.startsWith('#') && !hasPici && !hasHangxian) {
      const cleanLine = line.replace(/^#+\s*/, '').trim()
      if (!cleanLine.startsWith('{')) {
        break
      }
    }

    if (hasPici) {
      const match = line.match(/\{pici:\s*(\{.*\})\s*\}/)
      if (match) {
        try {
          piciData = new Function('return ' + match[1])()
        } catch (e) {
          console.error('解析 pici 数据失败:', e)
        }
      }
    }

    if (hasHangxian) {
      const match = line.match(/\{hangxian:\s*(\[.*\])\s*\}/)
      if (match) {
        try {
          hangxianData = new Function('return ' + match[1])()
        } catch (e) {
          console.error('解析 hangxian 数据失败:', e)
        }
      }
    }
  }

  return { piciData, hangxianData }
}

/**
 * 从接收到的数据中提取 Markdown 内容
 * @param content 原始内容(可能是Markdown、代码块或JSON格式)
 * @returns 提取后的Markdown字符串
 */
const extractMarkdownContent = (content: string): string => {
  if (content.trim().startsWith('#')) {
    return content
  }

  const markdownMatch = content.match(/```(?:markdown)?\s*([\s\S]*?)\s*```/)
  if (markdownMatch) {
    return markdownMatch[1]
  }

  const jsonMatch = content.match(/```json\s*([\s\S]*?)\s*```/)
  if (jsonMatch) {
    try {
      const data = JSON.parse(jsonMatch[1])
      return convertJsonToMarkdown(data)
    } catch (e) {
      console.warn('JSON 解析失败:', e)
    }
  }

  return content
}

/**
 * 将 JSON 格式的思维导图数据转换为 Markdown
 * @param data 包含 nodes 和 edges 的JSON对象
 * @returns Markdown格式的字符串
 */
const convertJsonToMarkdown = (data: any): string => {
  const { nodes, edges } = data

  if (!nodes || !edges) {
    console.warn('思维导图数据缺少 nodes 或 edges，无法转换')
    return ''
  }

  // 构建节点映射
  const nodeMap = new Map()
  nodes.forEach((node: any) => {
    nodeMap.set(node.id, node)
  })

  // 构建层级结构
  const buildHierarchy = (nodeId: string, visited = new Set()): string => {
    if (visited.has(nodeId)) return ''
    visited.add(nodeId)

    const node = nodeMap.get(nodeId)
    if (!node) return ''

    const level = node.level || 0
    const indent = '#'.repeat(level + 1)
    let result = `${indent} ${node.label || '未命名节点'}\n`

    // 递归处理子节点
    const childEdges = edges.filter((e: any) => e.from === nodeId)
    childEdges.forEach((edge: any) => {
      result += buildHierarchy(edge.to, new Set(visited))
    })

    return result
  }

  // 找到根节点
  const rootNode = nodes.find((n: any) => n.level === 0)
  if (!rootNode) {
    console.warn('思维导图数据中未找到根节点（level=0）')
    return ''
  }

  return buildHierarchy(rootNode.id)
}

/**
 * 处理思维导图数据
 * @param data 接收到的Markdown或JSON数据
 * @returns Promise
 */
const processMindMapData = (data: string) => {
  if (!data) {
    console.warn('[MindMap] 数据为空')
    return Promise.resolve()
  }

  // SSE实时渲染模式下,需要持续更新思维导图
  // 历史数据模式下,只初始化一次
  if (isInitialized.value && props.isHistoryMode) {
    return Promise.resolve()
  }

  return Promise.resolve()
    .then(() => {
      const markdown = extractMarkdownContent(data)
      markdownContent.value = markdown
      return markdown
    })
    .then(() => {
      return nextTick()
    })
    .then(() => {
      // 历史数据模式下等待一下,SSE模式立即渲染
      if (props.isHistoryMode) {
        return new Promise(resolve => setTimeout(resolve, 200))
      }
      return Promise.resolve()
    })
    .then(() => {
      // 历史数据模式显示loading
      if (props.isHistoryMode) {
        isLoadingMindMap.value = true
      }

      // 如果已经初始化过,更新数据而不是重新创建
      if (isInitialized.value && markmapInstance) {
        return updateMarkmap()
      }

      return initMarkmap()
    })
    .then(() => {
      isInitialized.value = true
    })
    .catch((error) => {
      console.error('[MindMap] 处理失败:', error)
      isLoadingMindMap.value = false
    })
}

onMounted(() => {
  if (props.receivedMessage && props.showMindMap && !isInitialized.value) {
    processMindMapData(props.receivedMessage)
  }
})

watch(() => props.receivedMessage, (newVal) => {
  if (newVal) {
    processMindMapData(newVal)
  }
})

/**
 * 更新已存在的思维导图数据
 * @returns Promise
 */
const updateMarkmap = () => {
  if (!markmapInstance || !markdownContent.value) {
    console.warn('[MindMap] 无法更新:实例或内容不存在')
    return Promise.resolve()
  }

  return Promise.resolve()
    .then(() => {
      return import('markmap-lib').then(({ Transformer }) => {
        const transformer = new Transformer()

        const filteredMarkdown = markdownContent.value
          .split('\n')
          .filter(line => !line.includes('{pici:') && !line.includes('{hangxian:'))
          .join('\n')

        const { root } = transformer.transform(filteredMarkdown)

        // 为节点树添加路径信息
        const addPaths = (node: any, path: number[] = []): any => {
          node.path = [...path]
          if (node.children) {
            node.children.forEach((child: any, index: number) => {
              addPaths(child, [...path, index + 1])
            })
          }
          return node
        }

        // 更新原始数据树
        rawTree = JSON.parse(JSON.stringify(root))
        addPaths(rawTree, [1])

        // 更新思维导图数据
        markmapInstance.setData(root)

        // 应用样式
        const container = document.getElementById('mindMapContainer')
        const svg = container?.querySelector('svg')
        if (svg) {
          applyMarkmapStyles(svg as SVGElement)
        }

        return markmapInstance
      })
    })
    .catch((error) => {
      console.error('[MindMap] 更新失败:', error)
    })
}

/**
 * 初始化思维导图
 * @returns Promise
 */
const initMarkmap = () => {
  if (isInitialized.value || markmapInstance) {
    return Promise.resolve()
  }

  const container = document.getElementById('mindMapContainer')
  if (!container) {
    console.error('[MindMap] 容器未找到')
    return Promise.reject(new Error('思维导图容器未找到'))
  }

  if (!markdownContent.value) {
    console.error('[MindMap] Markdown 内容为空')
    return Promise.reject(new Error('思维导图数据为空'))
  }

  return Promise.resolve()
    .then(() => {
      const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
      svg.style.width = '100%'
      svg.style.height = '100%'
      svg.style.background = 'transparent'
      container.appendChild(svg)
      return svg
    })
    .then((svg) => {
      return import('markmap-lib').then(({ Transformer }) => {
        const transformer = new Transformer()

        const filteredMarkdown = markdownContent.value
          .split('\n')
          .filter(line => !line.includes('{pici:') && !line.includes('{hangxian:'))
          .join('\n')

        const { root } = transformer.transform(filteredMarkdown)

        // 为节点树添加路径信息
        const addPaths = (node: any, path: number[] = []): any => {
          node.path = [...path]
          if (node.children) {
            node.children.forEach((child: any, index: number) => {
              addPaths(child, [...path, index + 1])
            })
          }
          return node
        }

        // 保留原始数据树，用于展开/收缩功能
        rawTree = JSON.parse(JSON.stringify(root))
        addPaths(rawTree, [1]) // 为原始树添加路径信息

        // 创建 Markmap 实例，设置主题色
        markmapInstance = Markmap.create(svg, {
          duration: 0,
          color: () => '#ffffff',
          pan: false, // 禁用拖拽平移
          // lineColor, nodeBorder, nodeBackground 等属性在类型定义中不存在，将在样式中设置
        })
        markmapInstance.setData(root)

        // 获取 D3 zoom 实例并重新配置
        const svgSelection = (markmapInstance as any).svg
        const d3Zoom = (markmapInstance as any).renderData?.zoom

        if (svgSelection && d3Zoom) {
          // 禁用双击缩放
          svgSelection.on('dblclick.zoom', null)

          // 重新配置 zoom 行为:允许滚轮缩放,禁止拖拽平移
          d3Zoom.filter((event: any) => {
            // 允许滚轮事件触发缩放
            if (event.type === 'wheel') return true
            // 允许 null 事件(编程式调用 transform)
            if (!event || event.type === undefined) return true
            // 阻止鼠标拖拽事件
            if (event.type === 'mousedown' || event.type === 'touchstart') return false
            return false
          })
        }

        // 应用初始文字颜色样式
        setTimeout(() => {
          const svgElement = container.querySelector('svg')
          if (svgElement) {
            svgElement.querySelectorAll('text').forEach(t => t.setAttribute('fill', '#D4FFEF'))
          }
        }, 100)

        return { svg, root }
      })
    })
    .then(({ svg, root }) => {
      // 应用自定义样式
      applyMarkmapStyles(svg)
      return root
    })
    .then((root) => {
      const lines = markdownContent.value.trim().split('\n')
      const firstLine = lines[0]?.trim()
      if (firstLine && firstLine.startsWith('#')) {
        rootNodeName.value = firstLine.replace(/^#+\s*/, '').trim()
      } else if (root && root.content) {
        rootNodeName.value = root.content
      } else {
        rootNodeName.value = '思维导图'
      }

      const svg = container.querySelector('svg')
      if (svg) {
        // 阻止 SVG 上的双击事件，防止触发缩放
        svg.addEventListener('dblclick', (event) => {
          event.preventDefault()
          event.stopPropagation()
        })

        /**
         * HTML实体解码
         * @param text 包含HTML实体的文本
         * @returns 解码后的文本
         */
        const decodeHtmlEntities = (text: string): string => {
          const textarea = document.createElement('textarea')
          textarea.innerHTML = text
          return textarea.value
        }

        /**
         * 从节点元素中提取文本内容
         */
        const getNodeText = (element: Element): string => {
          // 优先查找 foreignObject > div 结构（markmap 使用 HTML 渲染）
          const foreignObject = element.querySelector('foreignObject')
          if (foreignObject) {
            const div = foreignObject.querySelector('div')
            if (div) return div.textContent || ''
          }

          // 查找 text 元素
          const textElement = element.querySelector('text')
          return textElement?.textContent || ''
        }

        /**
         * 在树中查找匹配文本的节点
         */
        const findNodeByText = (node: any, searchText: string): any => {
          if (!node.content) return null

          const nodeText = decodeHtmlEntities(String(node.content)).trim()
          const target = searchText.trim()

          // 精确匹配或包含匹配
          if (nodeText === target ||
            nodeText.includes(target) ||
            target.includes(nodeText) ||
            nodeText.toLowerCase().includes(target.toLowerCase())) {
            return node
          }

          // 递归查找子节点
          if (node.children) {
            for (const child of node.children) {
              const found = findNodeByText(child, searchText)
              if (found) return found
            }
          }

          return null
        }

        /**
         * 处理节点点击事件
         */
        const handleNodeClick = (nodeElement: Element | null) => {
          if (!nodeElement) return

          const textContent = getNodeText(nodeElement)
          if (!textContent) return

          const clickedNode = findNodeByText(rawTree, textContent)
          if (!clickedNode) return

          // 只处理叶子节点
          const isLeafNode = !clickedNode.children || clickedNode.children.length === 0
          if (isLeafNode) {
            const text = decodeHtmlEntities(clickedNode.content || '无内容')
            parseNodeToDrawer(clickedNode, text)
          }
        }

        // 添加 SVG 点击事件监听
        svg.addEventListener('click', (event) => {
          const target = event.target as Element
          const nodeElement = target.closest('g[data-path]') ||
            target.closest('.markmap-node') ||
            target.closest('g')
          handleNodeClick(nodeElement)

          // 检查是否点击了圆圈(展开/收缩按钮)
          const circle = (event.target as Element).closest('circle')
          if (circle) {
            // 圆圈点击后会触发节点展开/收缩,需要等待动画完成后重新应用样式
            setTimeout(() => {
              const svgElement = container.querySelector('svg')
              if (svgElement) {
                applyMarkmapStyles(svgElement as SVGElement)
              }
            }, 100)
          }
        })
      }

      isLoadingMindMap.value = false
      emit('mindmapLoadingCompleted')
      return markmapInstance
    })
    .catch((error) => {
      console.error('Markmap 初始化失败:', error)
      isLoadingMindMap.value = false
      throw error
    })
}

/**
 * 应用思维导图自定义样式
 * @param svg SVG元素
 */
const applyMarkmapStyles = (svg: SVGElement) => {
  // 使用 requestAnimationFrame 确保在下一帧渲染前应用样式,避免闪烁
  requestAnimationFrame(() => {
    // 设置连接线样式
    const paths = svg.querySelectorAll('path')
    paths.forEach((path) => {
      path.setAttribute('stroke', '#D4FFEF')
      path.setAttribute('stroke-width', '1')
        ; (path as SVGElement).style.stroke = '#D4FFEF'
        ; (path as SVGElement).style.strokeWidth = '1'
        ; (path as SVGElement).style.fill = 'none'
    })

    // 设置节点背景样式
    const nodes = svg.querySelectorAll('g[data-depth], g[data-node-depth]')
    nodes.forEach((node) => {
      const rects = node.querySelectorAll('rect, .markmap-node-rect')
      rects.forEach((rect) => {
        rect.setAttribute('fill', 'rgba(0,103,78,0.8)')
        rect.setAttribute('stroke', 'transparent')
        rect.setAttribute('stroke-width', '0')
          ; (rect as SVGElement).style.fill = 'rgba(0,103,78,0.8)'
          ; (rect as SVGElement).style.stroke = 'transparent'
          ; (rect as SVGElement).style.strokeWidth = '0'
      })
    })

    // 隐藏第1、2、3级节点的 line 元素（markmap 的节点背景线），避免双重边框
    // 第4级及以上保持原样，不隐藏 line
    const styledNodeGroups = svg.querySelectorAll('g[data-depth="1"], g[data-depth="2"], g[data-depth="3"]')
    styledNodeGroups.forEach((node) => {
      const lines = node.querySelectorAll(':scope > line')
      lines.forEach((line) => {
        ; (line as SVGElement).style.display = 'none'
          ; (line as SVGElement).style.opacity = '0'
        line.setAttribute('stroke', 'none')
      })
    })

    // 设置文字颜色为 #D4FFEF
    const texts = svg.querySelectorAll('text')
    texts.forEach((text) => {
      text.setAttribute('fill', '#D4FFEF')
        ; (text as SVGElement).style.fill = '#D4FFEF'
    })

    // 为节点文字添加边框、圆角和背景（foreignObject > div > div 结构）
    const foreignObjects = svg.querySelectorAll('foreignObject')
    foreignObjects.forEach((fo) => {
      // 让 foreignObject 的点击穿透，避免挡住圆圈
      ; (fo as SVGElement).style.pointerEvents = 'none'

      // 获取父节点的 data-depth 或 data-path 来判断层级
      const parentG = fo.closest('g[data-depth], g[data-path]')
      let depth = 0

      if (parentG) {
        const depthAttr = parentG.getAttribute('data-depth')
        if (depthAttr) {
          depth = parseInt(depthAttr)
        } else {
          // 从 data-path 推断层级 (例如 "1.2.3" 表示第3级)
          const pathAttr = parentG.getAttribute('data-path')
          if (pathAttr) {
            depth = pathAttr.split('.').length - 1
          }
        }
      }

      // 为 foreignObject 添加 depth 类名,通过 CSS 控制尺寸
      if (depth === 1) {
        fo.classList.add('depth-1-node')
        // 通过内联样式设置 CSS 变量,用于 calc 计算
        const currentWidth = fo.getAttribute('width') || '0'
        const currentHeight = fo.getAttribute('height') || '0'
          ; (fo as SVGElement).style.setProperty('--original-width', currentWidth + 'px')
          ; (fo as SVGElement).style.setProperty('--original-height', currentHeight + 'px')
      } else if (depth === 2 || depth === 3) {
        fo.classList.add('depth-2-3-node')
        // 通过内联样式设置 CSS 变量,用于 calc 计算
        const currentWidth = fo.getAttribute('width') || '0'
        const currentHeight = fo.getAttribute('height') || '0'
          ; (fo as SVGElement).style.setProperty('--original-width', currentWidth + 'px')
          ; (fo as SVGElement).style.setProperty('--original-height', currentHeight + 'px')
      }
    })

    fitToContent()
  })
}

/**
 * 自适应内容并居中
 * @returns Promise
 */
const fitToContent = () => {
  if (!markmapInstance) return Promise.resolve()

  return Promise.resolve()
    .then(() => markmapInstance.fit())
    .then(() => {
      // 调用控制组件的更新方法
      controlsRef.value?.updateZoomLevel()
    })
    .catch((error) => {
      console.error('自适应内容失败:', error)
    })
}

/**
 * 解析节点数据到抽屉
 * @param _node 节点对象(未使用,保留参数以保持接口一致)
 * @param text 节点文本
 */
const parseNodeToDrawer = (_node: any, text: string) => {
  const { piciData, hangxianData } = extractDataFromMarkdown(text)

  if (piciData) {
    formData.value = {
      mainTask: piciData.mainTask || '',
      weaponMount: piciData.weaponMount || '',
      department: piciData.department || '',
      arrivalTime: piciData.arrivalTime || '',
      takeoffTime: piciData.takeoffTime || '',
      commShortWave: piciData.commShortWave || '',
      subTask: piciData.subTask || '',
      aircraftType: piciData.aircraftType || '',
      fuelAmount: piciData.fuelAmount || '',
      flightSegment: piciData.flightSegment || '',
      minFuel: piciData.minFuel || '',
      coverageRule: piciData.coverageRule || '',
      target: piciData.target || '',
      callsign: piciData.callsign || '',
      commandCode: piciData.commandCode || '',
      tailNumber: piciData.tailNumber || '',
      landingTime: piciData.landingTime || '',
      commandUnit: piciData.commandUnit || '',
      taskType: piciData.taskType || '',
      airfield: piciData.airfield || '',
      arrivalLocation: piciData.arrivalLocation || '',
      secondaryRadar: piciData.secondaryRadar || '',
      commUltraShort: piciData.commUltraShort || ''
    }
    selectedDrawerButton.value = 'A'
    drawerContentType.value = 'form'
  }

  if (hangxianData && hangxianData.length > 0) {
    tableData.value = hangxianData.map((item: any, index: number) => ({
      id: item.id || (index + 1),
      name: item.name || '',
      gridCoord: item.gridCoord || '',
      altitude: item.altitude || '',
      speed: item.speed || '',
      arrivalTime: item.arrivalTime || '',
      fuelRemaining: item.fuelRemaining || ''
    }))

    if (!piciData) {
      selectedDrawerButton.value = 'B'
      drawerContentType.value = 'text'
    }
  }

  if (!piciData && !hangxianData) {
    return
  }

  showDrawer.value = true
}

/**
 * 切换抽屉按钮
 * @param button 'A'=表单模式, 'B'=表格模式
 */
const selectDrawerButton = (button: 'A' | 'B') => {
  selectedDrawerButton.value = button
  if (button === 'A') {
    drawerContentType.value = 'form'
  } else {
    drawerContentType.value = 'text'
  }
}

/**
 * 重置思维导图状态
 */
const resetMindMapState = () => {
  isInitialized.value = false
  markdownContent.value = ''
  isLoadingMindMap.value = false
  showDrawer.value = false

  if (markmapInstance) {
    markmapInstance = null
  }
}

onUnmounted(() => {
  if (markmapInstance) {
    markmapInstance = null
  }
})

/**
 * 更新缩放级别（委托给控制组件）
 */
const updateZoomLevel = () => {
  controlsRef.value?.updateZoomLevel()
}

// 监听滚轮缩放事件，兼容用户直接滚动触发的缩放
const attachWheelListener = () => {
  const container = document.getElementById('mindMapContainer')
  if (!container) return
  // 使用节流避免频繁计算
  let ticking = false
  container.addEventListener('wheel', () => {
    if (!ticking) {
      ticking = true
      requestAnimationFrame(() => {
        updateZoomLevel()
        ticking = false
      })
    }
  }, { passive: true })
}

// 在初始化和更新后确保监听已添加
watch(isInitialized, (val) => {
  if (val) {
    attachWheelListener()
    updateZoomLevel()
  }
})

defineExpose({
  resetMindMapState
})
</script>

<style scoped>
.mindmap-wrapper {
  position: absolute;
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  overflow: hidden;
  /* 防止抽屉弹出时影响父容器出现滚动条 */
}

/* Loading 遮罩层样式 */
.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(2px);
  gap: 20px;
  z-index: 1000;
}

/* Loading GIF 样式 */
.loading-gif {
  width: 80px;
  height: 80px;
  object-fit: contain;
}

.loading-text {
  font-family: 'Source Han Sans', sans-serif;
  font-size: 16px;
  font-weight: 400;
  color: #D4FFEF;
  opacity: 0.8;
  animation: pulse 1.5s ease-in-out infinite;
  height: auto !important;
  margin: 0;
}

@keyframes pulse {

  0%,
  100% {
    opacity: 0.5;
  }

  50% {
    opacity: 1;
  }
}

.mindmap-container {
  width: 100%;
  height: 100%;
  min-height: 675px;
  background: transparent;
  overflow: hidden;
  position: relative;

  /* 覆盖 markmap 默认样式变量，将文字颜色改为白色 */
  --markmap-text-color: #D4FFEF;
  --markmap-a-color: #D4FFEF;
  --markmap-a-hover-color: #ffffff;
  --markmap-code-bg: rgba(255, 255, 255, 0.1);
  --markmap-code-color: #D4FFEF;
  --markmap-highlight-bg: rgba(212, 255, 239, 0.2);
  --markmap-circle-open-bg: rgba(255, 255, 255, 0.8);
  color: #D4FFEF;
}

/* 确保思维导图内部元素显示 */
.mindmap-container :deep(svg) {
  background: transparent !important;
  width: 100% !important;
  height: 100% !important;
}

.mindmap-container :deep(.smm-node) {
  cursor: pointer;
}

.mindmap-container :deep(.smm-node-text) {
  user-select: none;
}

/* 所有节点组添加 pointer 光标 */
.mindmap-container :deep(g[data-depth]),
.mindmap-container :deep(g[data-node-depth]),
.mindmap-container :deep(g.markmap-node),
.mindmap-container :deep(g[class*="node"]) {
  cursor: pointer !important;
}

/* 节点内的所有元素也添加 pointer 光标 */
.mindmap-container :deep(g[data-depth] *),
.mindmap-container :deep(g[data-node-depth] *),
.mindmap-container :deep(g.markmap-node *),
.mindmap-container :deep(g[class*="node"] *) {
  cursor: pointer !important;
}

/* 确保 SVG 文本元素可见 */
.mindmap-container :deep(text) {
  fill: #D4FFEF !important;
  font-size: 16px !important;
  font-family: '微软雅黑', Arial, sans-serif !important;
  pointer-events: none;
}

/* foreignObject 内的节点文字样式 - 添加边框、圆角、背景 */
/* 让 foreignObject 的点击穿透，避免挡住圆圈 */
.mindmap-container :deep(foreignObject) {
  pointer-events: none !important;
}

/* 第1级节点的 foreignObject - 通过 CSS 扩展尺寸和调整位置 */
.mindmap-container :deep(g[data-depth="1"] foreignObject) {
  transform: translate(-4px, 12px) !important;
}

/* 第1级节点的 foreignObject - 通过 CSS 扩展尺寸(需要配合 JavaScript 设置 CSS 变量) */
.mindmap-container :deep(foreignObject.depth-1-node) {
  width: calc(var(--original-width) + 30px) !important;
  height: calc(var(--original-height) + 20px) !important;
}

/* 第2级节点的 foreignObject - 通过纯 CSS 强制调整位置 */
.mindmap-container :deep(g[data-depth="2"] foreignObject) {
  transform: translate(-4px, 12px) !important;
}

/* 第2、3级节点的 foreignObject - 通过 CSS 扩展尺寸(需要配合 JavaScript 设置 CSS 变量) */
.mindmap-container :deep(foreignObject.depth-2-3-node) {
  width: calc(var(--original-width) + 30px) !important;
  height: calc(var(--original-height) + 20px) !important;
}

/* 第3级节点的 foreignObject - 通过纯 CSS 强制调整位置 */
.mindmap-container :deep(g[data-depth="3"] foreignObject) {
  transform: translate(-4px, 12px) !important;
}

/* 但让内层文字 div 可以接收点击 */
.mindmap-container :deep(foreignObject > div > div) {
  pointer-events: auto !important;
}

/* 第一级节点：红色边框，深紫红背景 */
.mindmap-container :deep(g[data-depth="1"] foreignObject > div > div),
.mindmap-container :deep(g[data-path="1"] foreignObject > div > div) {
  border: 1px solid #D4FFEF !important;
  border-radius: 6px !important;
  background: linear-gradient(180deg, rgba(0, 156, 118, 0.8) 0%, rgba(0, 50, 38, 0.8) 100%) !important;
  padding: 4px 8px !important;
  color: #D4FFEF !important;
  display: inline-block !important;
  white-space: nowrap !important;
  box-sizing: border-box !important;
}

/* 第二级节点：黄色边框，浅黄背景 */
.mindmap-container :deep(g[data-depth="2"] foreignObject > div > div) {
  border: 1px solid #D4FFEF !important;
  border-radius: 6px !important;
  background: rgba(0, 48, 37, 0.6) !important;
  padding: 4px 8px !important;
  color: #D4FFEF !important;
  display: inline-block !important;
  white-space: nowrap !important;
  box-sizing: border-box !important;
}

/* 第三级节点：黄色边框，浅黄背景 */
.mindmap-container :deep(g[data-depth="3"] foreignObject > div > div) {
  border: 1px solid #D4FFEF !important;
  border-radius: 6px !important;
  background: rgba(0, 48, 37, 0.6) !important;
  padding: 4px 8px !important;
  color: #D4FFEF !important;
  display: inline-block !important;
  white-space: nowrap !important;
  box-sizing: border-box !important;
}

/* 其他层级节点：无边框、无背景（保持原样） */
.mindmap-container :deep(g[data-depth]:not([data-depth="1"]):not([data-depth="2"]):not([data-depth="3"]) foreignObject > div > div) {
  border: none !important;
  background: transparent !important;
  padding: 0 !important;
  color: #D4FFEF !important;
  display: inline-block !important;
  white-space: nowrap !important;
}

/* 外层 div 保持透明，不添加样式 */
.mindmap-container :deep(foreignObject > div) {
  background: transparent !important;
  border: none !important;
  padding: 0 !important;
}

/* 隐藏节点组内的 line 元素，避免双重边框 */
/* 只隐藏第1、2、3级节点的 line，第4级及以上保持原样 */
.mindmap-container :deep(g[data-depth="1"] > line),
.mindmap-container :deep(g[data-depth="2"] > line),
.mindmap-container :deep(g[data-depth="3"] > line) {
  display: none !important;
  opacity: 0 !important;
  stroke: none !important;
}

/* 根节点文本样式 */
.mindmap-container :deep(g:first-of-type text) {
  fill: #D4FFEF !important;
  font-size: 16px !important;
  font-family: 'Source Han Sans', '微软雅黑', Arial, sans-serif !important;
  font-weight: normal !important;
}

/* 确保节点形状可见 */
.mindmap-container :deep(rect),
.mindmap-container :deep(circle) {
  stroke: #D4FFEF !important;
  stroke-width: 0;
  fill: #D4FFEF !important;
  /* fill-opacity: 0 !important; */
}

/* 思维导图连接线样式 */
.mindmap-container :deep(line),
.mindmap-container :deep(polyline) {
  stroke: #D4FFEF !important;
  stroke-width: 1 !important;
}

.mindmap-container :deep(polyline),
.mindmap-container :deep(path[fill="none"]),
.mindmap-container :deep(path[fill="transparent"]) {
  fill: none !important;
}

.mindmap-container :deep(path[fill="none"]),
.mindmap-container :deep(path[fill="transparent"]) {
  stroke: #D4FFEF !important;
  stroke-width: 1 !important;
}

/* 展开/收缩按钮样式 */
.mindmap-container :deep(.smm-expand-btn),
.mindmap-container :deep(.expand-btn),
.mindmap-container :deep([class*="expand"]) {
  fill: transparent !important;
  stroke: #D4FFEF !important;
  stroke-width: 1 !important;
}

.mindmap-container :deep(.smm-expand-btn circle),
.mindmap-container :deep(.expand-btn circle),
.mindmap-container :deep([class*="expand"] circle) {
  fill: transparent !important;
  stroke: #D4FFEF !important;
  stroke-width: 1 !important;
}

.mindmap-container :deep(.smm-expand-btn text),
.mindmap-container :deep(.expand-btn text),
.mindmap-container :deep([class*="expand"] text) {
  fill: #D4FFEF !important;
  font-size: 12px !important;
}

.mindmap-container :deep(.smm-expand-btn line),
.mindmap-container :deep(.expand-btn line),
.mindmap-container :deep([class*="expand"] line) {
  stroke: #D4FFEF !important;
  stroke-width: 1 !important;
}

/* 覆盖 markmap 类的样式 */
.mindmap-container :deep(.markmap) {
  --markmap-text-color: #D4FFEF !important;
  --markmap-a-color: #D4FFEF !important;
  --markmap-a-hover-color: #ffffff !important;
  --markmap-code-bg: rgba(255, 255, 255, 0.1) !important;
  --markmap-code-color: #D4FFEF !important;
  --markmap-highlight-bg: rgba(212, 255, 239, 0.2) !important;
  --markmap-circle-open-bg: rgba(255, 255, 255, 0.8) !important;
  color: #D4FFEF !important;
  font: 300 16px/20px '微软雅黑', Arial, sans-serif !important;
}

/* 强制覆盖 markmap 节点文字颜色 */
.mindmap-container :deep(.markmap text),
.mindmap-container :deep(.markmap-node text),
.mindmap-container :deep(.markmap g text) {
  fill: #D4FFEF !important;
  color: #D4FFEF !important;
}

/* 抽屉容器 */
.drawer-container {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  min-height: 583px;
  background: #002926;
  z-index: 2000;
  display: flex;
  flex-direction: column;
}

/* 抽屉头部 */
.drawer-header {
  height: 44px;
  background: rgba(0, 255, 192, 0.25);
  box-sizing: border-box;
  border-width: 1px 0px 1px 0px;
  border-style: solid;
  border-color: rgba(255, 255, 255, 0.3);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  font-family: Source Han Sans;
  font-size: 16px;
  font-weight: bold;
  line-height: normal;
  letter-spacing: 0em;
  font-variation-settings: "opsz" auto;
  font-feature-settings: "kern" on;
  color: #D4FFEF;
}

/* 抽屉关闭按钮 */
.drawer-close-btn {
  width: 20px;
  height: 20px;
  border: none;
  background: transparent;
  color: #D4FFEF;
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  line-height: 1;
  transition: transform 0.3s ease;
}

.drawer-close-btn:hover {
  transform: rotate(90deg);
}

/* 抽屉内容区域 */
.drawer-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  /* background: #002926; */
}

/* 抽屉按钮组 */
.drawer-actions {
  height: 48px;
  display: flex;
  align-items: center;
  gap: 0px;
  padding: 0 9px;
  background: #002926;
}

/* 抽屉操作按钮 */
.drawer-action-btn {
  padding: 0;
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.drawer-action-btn:hover {
  opacity: 0.8;
}

/* 操作2按钮左边距 */
.drawer-action-btn-2 {
  margin-left: -9px;
  width: 130px;
}

/* 抽屉按钮图片 */
.drawer-btn-img {
  display: block;
  height: 30px;
  width: 114px;
}

/* 抽屉按钮文字 */
.drawer-btn-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: Source Han Sans;
  font-size: 14px;
  font-weight: normal;
  line-height: normal;
  text-align: center;
  letter-spacing: 0em;
  font-variation-settings: "opsz" auto;
  font-feature-settings: "kern" on;
  color: #D4FFEF;
  pointer-events: none;
  white-space: nowrap;
}

/* 抽屉文本区域 */
.drawer-text {
  flex: 1;
  height: 0;
  max-height: 485px;
  padding: 11px 14px;
  border: 1px solid rgba(212, 255, 239, 0.2);
  margin: 0px 9px 6px 8px;
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.2);
  color: #D4FFEF;
  font-family: 'Source Han Sans', sans-serif;
  font-size: 14px;
  line-height: 1.6;
  overflow: hidden;
}

/* 抽屉表单布局 */
.drawer-form {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 23px;
  width: 100%;
  height: 100%;
  overflow-y: auto;
}

/* 表单滚动条样式 */
.drawer-form::-webkit-scrollbar,
.data-table tbody::-webkit-scrollbar {
  width: 6px;
}

.drawer-form::-webkit-scrollbar-track,
.data-table tbody::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.1);
}

.drawer-form::-webkit-scrollbar-thumb,
.data-table tbody::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.3);
  border-radius: 3px;
}

.drawer-form::-webkit-scrollbar-thumb:hover,
.data-table tbody::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.5);
}

/* 表单列 */
.form-column {
  display: flex;
  flex-direction: column;
  gap: 17px;
}

/* 表单字段 */
.form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* 字段标签和输入框共用字体样式 */
.field-label,
.field-input {
  font-family: Source Han Sans;
  font-size: 14px;
  font-weight: normal;
  line-height: normal;
  letter-spacing: 0em;
  font-variation-settings: "opsz" auto;
  font-feature-settings: "kern" on;
}

/* 字段标签 */
.field-label {
  color: #D4FFEF;
}

/* 字段输入框 */
.field-input {
  background: rgba(107, 126, 122, 0.2);
  color: #D4FFEF;
  border: 1px solid rgba(212, 255, 239, 0.2);
  border-radius: 2px;
  padding: 6px 10px;
  outline: none;
  transition: all 0.3s ease;
}

.field-input:focus {
  border-color: rgba(212, 255, 239, 0.5);
  background: rgba(107, 126, 122, 0.3);
}

/* 下拉框特殊样式 */
.form-field:has(select) {
  position: relative;
}

select.field-input {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 30px;
  cursor: pointer;
}

/* 下拉框箭头 */
.form-field:has(select)::after {
  content: '';
  position: absolute;
  right: 16px;
  bottom: 10px;
  width: 0;
  height: 0;
  border-left: 7.5px solid transparent;
  border-right: 7.5px solid transparent;
  border-top: 9px solid #D4FFEF;
  opacity: 0.4;
  pointer-events: none;
  border-radius: 1px;
}

/* 下拉框选项样式 */
.field-input option {
  background: #002926;
  color: #D4FFEF;
}

/* 表格容器 */
.table-container {
  width: 100%;
  height: 462px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* 表格样式 */
.data-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* 表头容器 */
.data-table thead {
  display: table;
  width: 100%;
  table-layout: fixed;
  flex-shrink: 0;
}

/* 表头行 */
.data-table thead tr {
  display: table-row;
}

/* 表头样式 */
.data-table thead th {
  background: rgba(0, 156, 118, 0.6);
  font-family: Source Han Sans;
  font-size: 14px;
  font-weight: 500;
  line-height: normal;
  letter-spacing: 0em;
  font-variation-settings: "opsz" auto;
  font-feature-settings: "kern" on;
  color: #FFFFFF;
  height: 36px;
  text-align: center;
  padding: 0 10px;
  display: table-cell;
}

/* 表体容器 */
.data-table tbody {
  display: block;
  width: 100%;
  overflow-y: auto;
  flex: 1;
}

/* 表体行 */
.data-table tbody tr {
  display: table;
  width: 100%;
  table-layout: fixed;
}

/* 表格单元格样式 */
.data-table tbody td {
  font-family: Source Han Sans;
  font-size: 14px;
  font-weight: 300;
  line-height: 36px;
  letter-spacing: 0em;
  font-variation-settings: "opsz" auto;
  font-feature-settings: "kern" on;
  color: #FFFFFF;
  height: 36px;
  text-align: center;
  padding: 0 10px;
  display: table-cell;
}

/* 单行背景 */
.data-table tbody tr.odd-row {
  background: rgba(0, 141, 122, 0.08);
}

/* 双行背景 */
.data-table tbody tr.even-row {
  background: rgba(0, 141, 122, 0);
}

/* 抽屉滑入滑出动画 */
.drawer-slide-enter-active,
.drawer-slide-leave-active {
  transition: transform 0.3s ease;
}

.drawer-slide-enter-from {
  transform: translateY(100%);
}

.drawer-slide-leave-to {
  transform: translateY(100%);
}

.drawer-slide-enter-to {
  transform: translateY(0);
}
</style>
